package cn.iocoder.yudao.module.ai.service.operationreceivemessage;

import cn.iocoder.yudao.framework.exception.BusinessException;
import cn.iocoder.yudao.module.ai.constant.DicConstant;
import cn.iocoder.yudao.module.ai.dal.dataobject.operationalarm.OperationAlarmDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.operationendcompany.OperationEndCompanyDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.operationequ.OperationEquDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.operationscene.OperationSceneDO;
import cn.iocoder.yudao.module.ai.dal.mysql.operationalarm.OperationAlarmMapper;
import cn.iocoder.yudao.module.ai.dal.mysql.operationequ.OperationEquMapper;
import cn.iocoder.yudao.module.ai.dal.mysql.operationscene.OperationSceneMapper;
import cn.iocoder.yudao.module.ai.service.operationalarm.OperationAlarmService;
import cn.iocoder.yudao.module.ai.service.operationendcompany.OperationEndCompanyService;
import cn.iocoder.yudao.module.ai.utils.sm.sm2.SM2Util;
import cn.iocoder.yudao.module.ai.utils.sm.sm3.SM3Util;
import cn.iocoder.yudao.module.infra.util.DateUtils;
import cn.iocoder.yudao.module.infra.util.StringUtils;
import com.alibaba.fastjson.JSONArray;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.ai.controller.admin.operationreceivemessage.vo.*;
import cn.iocoder.yudao.module.ai.dal.dataobject.operationreceivemessage.OperationReceiveMessageDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.ai.dal.mysql.operationreceivemessage.OperationReceiveMessageMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.*;

/**
 * 终端推送消息日志 Service 实现类
 *
 * @author 侯俊青
 */
@Service
@Validated
@Slf4j
public class OperationReceiveMessageServiceImpl implements OperationReceiveMessageService {

    @Resource
    private OperationReceiveMessageMapper operationReceiveMessageMapper;
    @Resource
    private OperationEndCompanyService operationEndCompanyService;
    @Resource
    private OperationAlarmService operationAlarmService;
    @Resource
    private OperationAlarmMapper operationAlarmMapper;
    @Resource
    private OperationEquMapper operationEquMapper;
    @Resource
    private OperationSceneMapper operationSceneMapper;

    private final SM3Util sm3Util = new SM3Util();
    private final SM2Util sm2Util = new SM2Util();

    @Override
    public Long createOperationReceiveMessage(OperationReceiveMessageSaveReqVO createReqVO) {
        // 插入
        OperationReceiveMessageDO operationReceiveMessage = BeanUtils.toBean(createReqVO, OperationReceiveMessageDO.class);
        operationReceiveMessageMapper.insert(operationReceiveMessage);
        // 返回
        return operationReceiveMessage.getId();
    }

    @Override
    public void updateOperationReceiveMessage(OperationReceiveMessageSaveReqVO updateReqVO) {
        // 校验存在
        validateOperationReceiveMessageExists(updateReqVO.getId());
        // 更新
        OperationReceiveMessageDO updateObj = BeanUtils.toBean(updateReqVO, OperationReceiveMessageDO.class);
        operationReceiveMessageMapper.updateById(updateObj);
    }

    @Override
    public void deleteOperationReceiveMessage(Long id) {
        // 校验存在
        validateOperationReceiveMessageExists(id);
        // 删除
        operationReceiveMessageMapper.deleteById(id);
    }

    private void validateOperationReceiveMessageExists(Long id) {
        if (operationReceiveMessageMapper.selectById(id) == null) {
            throw exception(OPERATION_RECEIVE_MESSAGE_NOT_EXISTS);
        }
    }

    @Override
    public OperationReceiveMessageDO getOperationReceiveMessage(Long id) {
        return operationReceiveMessageMapper.selectById(id);
    }

    @Override
    public PageResult<OperationReceiveMessageDO> getOperationReceiveMessagePage(OperationReceiveMessagePageReqVO pageReqVO) {
        return operationReceiveMessageMapper.selectPage(pageReqVO);
    }

    @Override
    public Long report(OperationReceiveMessageSaveReqSimpleVO reportReqVO) {
        OperationReceiveMessageSaveReqVO saveReqVO = new OperationReceiveMessageSaveReqVO();
        saveReqVO.setParamAppid(reportReqVO.getAppid());
        saveReqVO.setParamData(reportReqVO.getData());
        saveReqVO.setParamReqtime(reportReqVO.getReqtime());
        saveReqVO.setParamSign( reportReqVO.getSign());
        saveReqVO.setParamTranscode(reportReqVO.getTranscode());

        // 首先进行数据解密
        String jData = SM2Util.decryptBySM2(reportReqVO.getData(), DicConstant.operation_report_privateKey);//私钥解密
        // 解密后
        saveReqVO.setDataDecrypt(jData);

        JSONArray jsonArray = JSONArray.parseArray(jData);
        if(null == jsonArray || jsonArray.isEmpty()){
            throw new BusinessException("数据不能为空");
        }

        String companyId = jsonArray.getJSONObject(0).getString("companyId");
        // 解密后
        saveReqVO.setCompanyId(companyId);
        if(null == companyId || companyId.isEmpty()){
            throw new BusinessException("数据错误，companyId不能为空");
        }
        OperationEndCompanyDO companyDO = operationEndCompanyService.getByCompanyId(companyId);
        if(null == companyDO){
            throw new BusinessException("数据错误，companyId不存在");
        }
        String auth = String.format("%s%s%s%s",jData,reportReqVO.getReqtime(),companyDO.getAppKey(),companyDO.getAppSecret());

        try {
            boolean infoverify = sm3Util.infoverify(reportReqVO.getSign(), auth);//验签
            if(infoverify){
                // 保存一下
                Long operationReceiveMessageId = createOperationReceiveMessage(saveReqVO);
                // 解析 告警
                Set<String> alarmIds = new HashSet<>();
                if(DicConstant.operation_transcode_AlARM101.equals(reportReqVO.getTranscode())){
                    List<OperationAlarmDO> operationAlarmDOS = JSONArray.parseArray(jData, OperationAlarmDO.class);
                    for (int i = 0; i < operationAlarmDOS.size(); i++) {
                        OperationAlarmDO operationAlarmDO = operationAlarmDOS.get(i);
                        // 处理基本信息
                        operationAlarmDO.setFromMessageId(operationReceiveMessageId);
                        operationAlarmDO.setFromMessageIndex(i);
                        operationAlarmDO.setCompanyId(companyId);
                        if(StringUtils.isNotBlank(operationAlarmDO.getAlarmId())){
                            alarmIds.add(operationAlarmDO.getAlarmId());
                        }
                        // 处理开始结束时间
                        String key_startTime = "startTime";
                        String key_endTime = "endTime";
                        String startTime = jsonArray.getJSONObject(i).getString(key_startTime);
                        String endTime = jsonArray.getJSONObject(i).getString(key_endTime);
                        if(jsonArray.getJSONObject(i).containsKey(key_startTime) && StringUtils.isNotBlank(startTime)){
                            Date date = new SimpleDateFormat(DateUtils.YYYY_MM_DD_HH_MM_SS).parse(startTime);
                            LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
                            operationAlarmDO.setStartTime(localDateTime);
                        }
                        if(jsonArray.getJSONObject(i).containsKey(key_endTime) && StringUtils.isNotBlank(endTime)){
                            Date date = new SimpleDateFormat(DateUtils.YYYY_MM_DD_HH_MM_SS).parse(endTime);
                            LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
                            operationAlarmDO.setEndTime(localDateTime);
                        }
                    }
                    // 删除已经存在相同的
                    List<OperationAlarmDO> sameAlarmDos = operationAlarmMapper.selectList(OperationAlarmDO::getAlarmId, alarmIds);
                    if(CollectionUtils.isNotEmpty(sameAlarmDos)){
                        List<Long> ids = sameAlarmDos.stream().map(OperationAlarmDO::getId).collect(Collectors.toList());
                        operationAlarmMapper.deleteBatchIds(ids);
                    }
                    // 批量保存告警记录
                    operationAlarmMapper.insertBatch(operationAlarmDOS);
                }else if(DicConstant.operation_transcode_EQU102.equals(reportReqVO.getTranscode())){
                    List<OperationEquDO> dos = JSONArray.parseArray(jData, OperationEquDO.class);
                    for (int i = 0; i < dos.size(); i++) {
                        OperationEquDO aDo = dos.get(i);
                        // 处理基本信息
                        aDo.setFromMessageId(operationReceiveMessageId);
                        aDo.setFromMessageIndex(i);
                        aDo.setCompanyId(companyId);
                        aDo.setCpuTemperature(jsonArray.getJSONObject(i).getString("temperature"));
                        aDo.setCpuLoad(jsonArray.getJSONObject(i).getString("load"));
                    }
                    // 删除已经存在的
                    operationEquMapper.delete(OperationEquDO::getCompanyId, companyId);
                    // 批量保存
                    operationEquMapper.insertBatch(dos);
                }else if(DicConstant.operation_transcode_SCENE103.equals(reportReqVO.getTranscode())){
                    List<OperationSceneDO> dos = JSONArray.parseArray(jData, OperationSceneDO.class);
                    for (int i = 0; i < dos.size(); i++) {
                        OperationSceneDO aDo = dos.get(i);
                        // 处理基本信息
                        aDo.setFromMessageId(operationReceiveMessageId);
                        aDo.setFromMessageIndex(i);
                        aDo.setCompanyId(companyId);
                    }
                    // 删除已经存在的
                    operationSceneMapper.delete(OperationSceneDO::getCompanyId, companyId);
                    // 批量保存
                    operationSceneMapper.insertBatch(dos);
                }

            }else {
                throw new BusinessException("数据错误，签名验证失败");
            }
        } catch (Exception e) {
            log.error("数据错误，签名验证失败",e);
            throw new BusinessException("数据错误，签名验证失败");
        }
        return 0L;
    }
}